<?php
/* 
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

class Core_IO_SMTPConnection {

    private $SMTPServerInformation;

    private $resConnection;
    private $arrConversation = array();

    private $boolSenderIsSent = false;
    private $boolAddedReciever = false;

    /**
     * @throws If an error occoured while connecting.
     * @throws If not answered as expected on 'EHLO'.
     * @param Core_IO_Mail_SMTPServerInformation $SMTPServerInformation
     */
    function __cosntruct ( Core_IO_SMTPServerInformation $SMTPServerInformation ) {
        $this->SMTPServerInformation = $SMTPServerInformation;
        $this->connect();
        echo " HEST ";
    }

    private function connect() {

        $this->resConnection = fsockopen( $this->SMTPServerInformation->Host, $this->SMTPServerInformation->Port, $errno, $errstr, $this->SMTPServerInformation->Timeout );
        $strResponse = fgets( $resConnection, 4096 );
echo "!" . $strResponse . "!";
        if( !$resConnection or ( substr( $strResponse, 0, 3 ) != "220" ) ) {
            throw new Exception ( "Failed to connect to " . $strHost . ". Server said: " . $strResponse );
        }

        $arr = array( "SERVER", $strResponse );
        $this->arrConversation[] = $arr;


        // Say hello to the server.
        $strMessage = "EHLO " . $_SERVER['SERVER_ADDR'] . "\r\n";

        if ( !$this->sendMessage( $strMessage, 250, false ) ) {

            // According to RFC 5321, 3.2 we have to fall back on HELO if EHLO fails.
            $strMessage = "HELO " . $_SERVER['SERVER_ADDR'] . "\r\n";
            $this->sendMessage( $strMessage );

        }


        if ( $this->SMTPServerInformation->Authenticate ) {

            // Request authorized login.
            $strMessage = "AUTH LOGIN\r\n";
            $this->sendMessage( $strMessage );

            // Send username.
            $strMessage = base64_encode( $this->SMTPServerInformation->Username ) . "\r\n";
            $this->sendMessage( $strMessage );

            // Send password.
            $strMessage = base64_encode( $this->SMTPServerInformation->Password ) . "\r\n";
            $this->sendMessage( $strMessage );

        }

    }

    /**
     * Gets the whole conversation, so far.
     *
     * @return array
     */
    public function getConversation () {
        return $this->arrConversation;
    }

    public function setSender ( $strAddress ) {

        // Here, we're not permitting to send "MAIL FROM: ..." twice.
        // TODO: Investigate what the standard says about sending "MAIL FROM: ..." twice.

        if ( $this->boolSenderIsSent == false ) {

            $strMessage = "MAIL FROM: <" . $strAddress . ">\r\n";
            $this->sendMessage( $strMessage );

            $this->boolSenderIsSent = true;

        }

    }

    public function addReciever ( $strAddress ) {

        $strMessage = "RCPT TO: <" . $strAddress . ">\r\n";
        $this->sendMessage( $strMessage );

        $this->boolAddedReciever = true;

    }

    /**
     * Sets the data (aka the SMTP body).
     * 
     * @param string $strData 
     */
    public function setData ( $strData ) {

        // Prepare to send data.
        $strMessage = "DATA\r\n";
        $this->sendMessage( $strMessage, 354 );

        // Send data.
        $strMessage = $strData . "\r\n.\r\n";
        $this->sendMessage( $strMessage );

    }

    public function close () {

        // The actual connection is closed by the server after we've said goodbye.

        $strMessage = "QUIT\r\n";
        $this->sendMessage( $strMessage, 221 );

    }

    private function sendMessage ( $strMessage, $intExpectedCode = 250, $boolThrowException = true ) {

        // Add the message to the conversation.
        $arr = array( "CLIENT", $strMessage );
        $this->arrConversation[] = $arr;

        // Send the message.
        fputs( $this->resConnection, $strMessage );

        // Retrieve a response.
        $strResponse = fgets( $resConnection, 4096 );


        if ( substr( $strResponse, 0, 3 ) != $intExpectedCode ) {
            if ( $boolThrowException == true ) {
                // Throw an exception if the response was not as expected.
                throw new Exception( "Server said: " . $strResponse );
            } else {
                return false;
            }
        }

        // Add the response to the conversation.
        $arr = array( "SERVER", $strResponse );
        $this->arrConversation[] = $arr;

        echo "<br>.<br>"; print_r( $this->arrConversation ); echo "<br>.<br>";

        return true;

    }

}

?>
